ACM POJ 2245Lotto解题报告

http://poj.org/problem?id=2245

Lotto

在玩德国游戏Lotto时,要从集合{12,……,49}中取出六个数。

一个非常流行的玩法(尽管这种玩法并不能增加你赢的机会)是从这49个数字中取出k个数字(6<k)组成子集S。然后玩游戏的时候仅从S中取出数字。

例如,当k=8S=12358132134时,有28种可能的游戏:

[1,2,3,5,8,13][1,2,3,5,8,21][1,2,3,5,8,34][1,2,3,5,13,21],……,[3,5,8,13,21,34]

编一个程序,读入k的值和集合S,打印仅从S中取数的所有可能游戏。

输入

输入文件包括一个或多个测试情形。

每种情形一行,由多个整数组成,整数之间用空格分隔。行首整数即为k值(6<k<13)。

接着是用于描述集合Sk个整数,全部以升序排列。

k的位置输入零(0)即表示输入结束。

输出

对于每一个测试情形,打印出所有可能游戏,每个游戏一行。

每个游戏中的数字必须以升序排列,每两个之间用一个空格分隔。而这些游戏要用类似于字典编纂的方式排序,也就是说,先对最低位排序,然后是第二低位,依次类推,就像输出举例中演示的那样。

输入样例

7 1 2 3 4 5 6 7
8 1 2 3 5 8 13 21 34

0

输出样例

1 2 3 4 5 6
1 2 3 4 5 7
1 2 3 4 6 7
1 2 3 5 6 7
1 2 4 5 6 7
1 3 4 5 6 7
2 3 4 5 6 7
 
1 2 3 5 8 13
1 2 3 5 8 21
1 2 3 5 8 34
1 2 3 5 13 21
1 2 3 5 13 34
1 2 3 5 21 34
1 2 3 8 13 21
1 2 3 8 13 34
1 2 3 8 21 34
1 2 3 13 21 34
1 2 5 8 13 21
1 2 5 8 13 34
1 2 5 8 21 34
1 2 5 13 21 34
1 2 8 13 21 34
1 3 5 8 13 21
1 3 5 8 13 34
1 3 5 8 21 34
1 3 5 13 21 34
1 3 8 13 21 34
1 5 8 13 21 34
2 3 5 8 13 21
2 3 5 8 13 34
2 3 5 8 21 34
2 3 5 13 21 34
2 3 8 13 21 34
2 5 8 13 21 34
3 5 8 13 21 34

 

 

 

本题就是产生组合数的方法。

#include<stdio.h>

#include<iostream>

using namespace std;

#define  MAXN 20

int p[MAXN];

void print(int *a,int m)  //输出

{

    int i,cnt;

    for(i=0;i<m-1;i++) {cnt=a[i];cout<<p[cnt]<<' ';}

    cnt=a[m-1];

    cout<<p[cnt]<<endl;

}   

//先是产生1234567......这样的组合数,再利用下标输出需要的组合数

 

void GenComb(int *a,int n,int m)//产生下一个组合数

{

    int i,j,t;

    print(a,m);

    for(j=m-1;j>=0;j--)

      if(a[j]<n-m+j+1)break;

    t=a[j];

    for(i=0;i<=m-j-1;i++)

      a[j+i]=t+i+1;

}

void GenAllComb(int *a,int n,int m)

{

    int index;

    for(index=0;index<m;index++)a[index]=index+1;//初始化,产生123...这样的数列

    index=0;

    while(index<=n-m)//index指向的是第一个组合数 的小标,当index大于n-m时说明,已经到达尾部。

    {

        GenComb(a,n,m);

        if(a[0]>index+1)index++;

    }   

}  

int main()

{

    int n,m=6,a[MAXN],i;

    int first=0;//POJ上的题目要求最后一个不要产生空格,故除第一组外其余前面产生空格

    while(cin>>n,n)

    {

        if(first)  cout<<endl;

        first=1;

        for(i=1;i<=n;i++)  cin>>p[i];

        GenAllComb(a,n,m);

       

    }

    return 0;   

}   

(此程序在POJGCC++通不过,用C++,Accept了。。。 奇怪了)

#include<stdio.h>
#include
<iostream>
using namespace std;
#define MAXN 20
int p[MAXN];
void print(int *a,int m) //输出
{
int i,cnt;
for(i=0;i<m-1;i++) {cnt=a[i];cout<<p[cnt]<<' ';}
cnt
=a[m-1];
cout
<<p[cnt]<<endl;
}
//先是产生1,2,3,4,5,6,7......这样的组合数,再利用下标输出需要的组合数

void GenComb(int *a,int n,int m)//产生下一个组合数
{
int i,j,t;
print(a,m);
for(j=m-1;j>=0;j--)
if(a[j]<n-m+j+1)break;
t
=a[j];
for(i=0;i<=m-j-1;i++)
a[j
+i]=t+i+1;
}
void GenAllComb(int *a,int n,int m)
{
int index;
for(index=0;index<m;index++)a[index]=index+1;//初始化,产生1,2,3...这样的数列
index=0;
while(index<=n-m)//index指向的是第一个组合数 的小标,当index大于n-m时说明,已经到达尾部。
{
GenComb(a,n,m);
if(a[0]>index+1)index++;
}
}
int main()
{
int n,m=6,a[MAXN],i;
int first=0;//POJ上的题目要求最后一个不要产生空格,故除第一组外其余前面产生空格
while(cin>>n,n)
{
if(first) cout<<endl;
first
=1;
for(i=1;i<=n;i++) cin>>p[i];
GenAllComb(a,n,m);

}
return 0;
}
 

下面的程序是学习了网上的写出来的,比较简洁,推荐!!!

#include<stdio.h>
#include<string.h>//memset函数头文件
int K;//每一组数的个数
int num[13];
int chosed[13];
void find(int st,int n)
{
    int i,first;
    if(n==6)
    {
        first=1;
        for(i=0;i<K;i++)
        {
            if(chosed[i])
            {
                if(first==1) {printf("%d",num[i]);first=0;}
                else printf(" %d",num[i]);
            }    
        }
        printf("\n");return;    
    }
    for(i=st;i<K;i++)
    {
        if(!chosed[i])
        {
            chosed[i]=1;
            find(i+1,n+1);
            chosed[i]=0;
        }    
    }        
} 
int main()
{
    int i,first=1;
    while(scanf("%d",&K)!=EOF&&K)
    {
        for(i=0;i<K;i++) scanf("%d",&num[i]);
        if(first==1)first=0;
        else printf("\n");
        memset(chosed,0,sizeof(chosed));
        find(0,0);
    }  
    return 0;  
}  

posted on 2011-07-22 21:31  kuangbin  阅读(953)  评论(0编辑  收藏  举报

导航

JAVASCRIPT: